package com.waikuai.shop.service.impl;

import com.waikuai.shop.dto.StatisticsQueryDTO;
import com.waikuai.shop.mapper.StatisticsMapper;
import com.waikuai.shop.service.StatisticsService;
import com.waikuai.shop.vo.CategoryDistributionVO;
import com.waikuai.shop.vo.OrderTrendVO;
import com.waikuai.shop.vo.SalesRankingVO;
import com.waikuai.shop.vo.StatisticsOverviewVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.List;

/**
 * 统计服务实现类
 * @author waikuai
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StatisticsServiceImpl implements StatisticsService {

    private final StatisticsMapper statisticsMapper;

    @Override
    public StatisticsOverviewVO getOverviewStatistics(StatisticsQueryDTO.TimeRange timeRange) {
        // 获取时间范围
        LocalDateTime[] timeRangeArray = getTimeRange(timeRange);
        LocalDateTime startTime = timeRangeArray[0];
        LocalDateTime endTime = timeRangeArray[1];

        // 获取上一个时间范围（用于计算环比）
        LocalDateTime[] lastTimeRangeArray = getLastTimeRange(timeRange);
        LocalDateTime lastStartTime = lastTimeRangeArray[0];
        LocalDateTime lastEndTime = lastTimeRangeArray[1];

        // 当前时间范围统计
        Long totalOrders = statisticsMapper.countOrders(startTime, endTime);
        BigDecimal totalSalesAmount = statisticsMapper.sumSalesAmount(startTime, endTime);
        if (totalSalesAmount == null) {
            totalSalesAmount = BigDecimal.ZERO;
        }
        Long totalUsers = statisticsMapper.countNewUsers(startTime, endTime);

        // 上一个时间范围统计
        Long lastTotalOrders = statisticsMapper.countOrders(lastStartTime, lastEndTime);
        BigDecimal lastTotalSalesAmount = statisticsMapper.sumSalesAmount(lastStartTime, lastEndTime);
        if (lastTotalSalesAmount == null) {
            lastTotalSalesAmount = BigDecimal.ZERO;
        }
        Long lastTotalUsers = statisticsMapper.countNewUsers(lastStartTime, lastEndTime);

        // 计算环比增长率
        BigDecimal orderGrowthRate = calculateGrowthRate(totalOrders, lastTotalOrders);
        BigDecimal salesGrowthRate = calculateGrowthRate(totalSalesAmount, lastTotalSalesAmount);
        BigDecimal userGrowthRate = calculateGrowthRate(totalUsers, lastTotalUsers);

        // 计算额度卡兑换率
        Long totalCards = statisticsMapper.countTotalCards();
        Long exchangedCards = statisticsMapper.countExchangedCards();
        BigDecimal cardExchangeRate = BigDecimal.ZERO;
        if (totalCards != null && totalCards > 0 && exchangedCards != null) {
            cardExchangeRate = new BigDecimal(exchangedCards)
                    .multiply(new BigDecimal(100))
                    .divide(new BigDecimal(totalCards), 2, RoundingMode.HALF_UP);
        }

        return StatisticsOverviewVO.builder()
                .totalOrders(totalOrders)
                .totalSalesAmount(totalSalesAmount)
                .totalUsers(totalUsers)
                .cardExchangeRate(cardExchangeRate)
                .orderGrowthRate(orderGrowthRate)
                .salesGrowthRate(salesGrowthRate)
                .userGrowthRate(userGrowthRate)
                .build();
    }

    @Override
    public List<OrderTrendVO> getOrderTrend(StatisticsQueryDTO.TimeRange timeRange) {
        LocalDateTime[] timeRangeArray = getTimeRange(timeRange);
        LocalDateTime startTime = timeRangeArray[0];
        LocalDateTime endTime = timeRangeArray[1];

        // 今天按小时统计，其他按天统计
        if (timeRange == StatisticsQueryDTO.TimeRange.TODAY) {
            return statisticsMapper.selectOrderTrendByHour(startTime, endTime);
        } else {
            return statisticsMapper.selectOrderTrendByDay(startTime, endTime);
        }
    }

    @Override
    public List<CategoryDistributionVO> getCategoryDistribution(StatisticsQueryDTO.TimeRange timeRange) {
        LocalDateTime[] timeRangeArray = getTimeRange(timeRange);
        LocalDateTime startTime = timeRangeArray[0];
        LocalDateTime endTime = timeRangeArray[1];

        List<CategoryDistributionVO> distributions = statisticsMapper.selectCategoryDistribution(startTime, endTime);

        // 计算总销售额
        BigDecimal totalSalesAmount = distributions.stream()
                .map(CategoryDistributionVO::getSalesAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算每个分类的占比
        if (totalSalesAmount.compareTo(BigDecimal.ZERO) > 0) {
            distributions.forEach(distribution -> {
                BigDecimal percentage = distribution.getSalesAmount()
                        .multiply(new BigDecimal(100))
                        .divide(totalSalesAmount, 2, RoundingMode.HALF_UP);
                distribution.setPercentage(percentage);
            });
        }

        return distributions;
    }

    @Override
    public List<SalesRankingVO> getTopProducts(StatisticsQueryDTO.TimeRange timeRange, Integer limit) {
        LocalDateTime[] timeRangeArray = getTimeRange(timeRange);
        LocalDateTime startTime = timeRangeArray[0];
        LocalDateTime endTime = timeRangeArray[1];

        if (limit == null || limit <= 0) {
            limit = 10;
        }

        List<SalesRankingVO> rankings = statisticsMapper.selectTopProducts(startTime, endTime, limit);

        // 设置排名
        for (int i = 0; i < rankings.size(); i++) {
            rankings.get(i).setRanking(i + 1);
        }

        return rankings;
    }

    /**
     * 获取时间范围
     */
    private LocalDateTime[] getTimeRange(StatisticsQueryDTO.TimeRange timeRange) {
        LocalDateTime startTime;
        LocalDateTime endTime = LocalDateTime.now();

        switch (timeRange) {
            case TODAY:
                startTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
                break;
            case WEEK:
                startTime = LocalDateTime.of(
                        LocalDate.now().with(TemporalAdjusters.previousOrSame(java.time.DayOfWeek.MONDAY)),
                        LocalTime.MIN
                );
                break;
            case MONTH:
                startTime = LocalDateTime.of(
                        LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()),
                        LocalTime.MIN
                );
                break;
            case YEAR:
                startTime = LocalDateTime.of(
                        LocalDate.now().with(TemporalAdjusters.firstDayOfYear()),
                        LocalTime.MIN
                );
                break;
            default:
                startTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        }

        return new LocalDateTime[]{startTime, endTime};
    }

    /**
     * 获取上一个时间范围（用于计算环比）
     */
    private LocalDateTime[] getLastTimeRange(StatisticsQueryDTO.TimeRange timeRange) {
        LocalDateTime[] currentRange = getTimeRange(timeRange);
        LocalDateTime startTime = currentRange[0];
        LocalDateTime endTime = currentRange[1];

        LocalDateTime lastStartTime;
        LocalDateTime lastEndTime;

        switch (timeRange) {
            case TODAY:
                lastStartTime = startTime.minusDays(1);
                lastEndTime = endTime.minusDays(1);
                break;
            case WEEK:
                lastStartTime = startTime.minusWeeks(1);
                lastEndTime = endTime.minusWeeks(1);
                break;
            case MONTH:
                lastStartTime = startTime.minusMonths(1);
                lastEndTime = endTime.minusMonths(1);
                break;
            case YEAR:
                lastStartTime = startTime.minusYears(1);
                lastEndTime = endTime.minusYears(1);
                break;
            default:
                lastStartTime = startTime.minusDays(1);
                lastEndTime = endTime.minusDays(1);
        }

        return new LocalDateTime[]{lastStartTime, lastEndTime};
    }

    /**
     * 计算环比增长率
     */
    private BigDecimal calculateGrowthRate(Long current, Long last) {
        if (last == null || last == 0) {
            return current != null && current > 0 ? new BigDecimal(100) : BigDecimal.ZERO;
        }
        if (current == null) {
            current = 0L;
        }
        return new BigDecimal(current - last)
                .multiply(new BigDecimal(100))
                .divide(new BigDecimal(last), 2, RoundingMode.HALF_UP);
    }

    /**
     * 计算环比增长率（BigDecimal版本）
     */
    private BigDecimal calculateGrowthRate(BigDecimal current, BigDecimal last) {
        if (last == null || last.compareTo(BigDecimal.ZERO) == 0) {
            return current != null && current.compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal(100) : BigDecimal.ZERO;
        }
        if (current == null) {
            current = BigDecimal.ZERO;
        }
        return current.subtract(last)
                .multiply(new BigDecimal(100))
                .divide(last, 2, RoundingMode.HALF_UP);
    }
}

